package opt_context

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup

func go_context_cancel() {
	// BackGroup
	ctx, cancelFunc := context.WithCancel(context.Background())

	wg.Add(1)

	go func(ctx context.Context) {
	LOOP:
		for {
			fmt.Println("worker start run")
			select {
			case <-ctx.Done():
				break LOOP
			default:

			}
		}
		wg.Done()
	}(ctx)

	time.Sleep(time.Second * 3)
	// 手动退出自旋 for{}
	cancelFunc()
	wg.Wait()
	fmt.Println("finish")
}

func go_context_with_deadline() {
	durtion := time.Now().Add(time.Second * 2)

	deadline, cancelFunc := context.WithDeadline(context.TODO(), durtion)
	// 手动取消自旋 : err: context canceled
	defer cancelFunc()

	select {
	// 1 Second 后执行
	case <-time.After(4 * time.Second):
		fmt.Println("run  normal ")
		// durtion 时间已到或手动cancelFunc
	case <-deadline.Done():
		// 超时：context deadline exceeded
		fmt.Println(deadline.Err())
	}
}

func go_context_with_value() {
	value := context.WithValue(context.TODO(), "str", "value")

	wg.Add(1)

	go func(ctx context.Context) {
		// 数据传递
		a := ctx.Value("str")
	Out:
		for {
			fmt.Println("get str ", a)
			time.Sleep(time.Millisecond * 10)
			select {
			case <-ctx.Done():
				break Out
			default:

			}
		}
	}(value)
	time.Sleep(time.Second * 5)

	wg.Wait()
}

func handle_req(ctx context.Context) {
	go write_block(ctx)
	go write_block_1(ctx)
	for {
		select {
		case <-ctx.Done():
			fmt.Println("parent thread done")
			return
		default:
			fmt.Println("======= parent_thread is spin")
			time.Sleep(2 * time.Second)
		}

	}
}

func write_block(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("========write block Run")
			return
		default:
			fmt.Println("======= thread1 is spin")
			time.Sleep(2 * time.Second)
		}
	}
}

func write_block_1(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("========write block_1 Run")
			return
		default:
			fmt.Println("======= thread_2 is spin")
			time.Sleep(2 * time.Second)
		}
	}
}
